﻿using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;

namespace Neoit.Utils.Tools
{
    /// <summary>
    /// 多线程执行任务
    /// </summary>
    public class MultiTaskExecutor
    {
        /// <summary>
        /// 多线程执行Func并返回结果集
        /// </summary>
        /// <typeparam name="TInput">输入参数的类型</typeparam>
        /// <typeparam name="TResult">返回结果的类型</typeparam>
        /// <param name="taskFunc">要执行的方法，接收一个输入参数并返回结果的Task</param>
        /// <param name="inputs">输入参数列表</param>
        /// <param name="maxConcurrency">最大并发数（默认为5）</param>
        /// <returns>返回所有任务结果的列表</returns>
        public static async Task<ConcurrentBag<TResult>> ExecuteTasksAsync<TInput, TResult>(
            Func<TInput, Task<TResult>> taskFunc,
            List<TInput> inputs,
            int maxConcurrency = 5)
        {
            // 用于控制并发线程数的SemaphoreSlim
            using var semaphore = new SemaphoreSlim(maxConcurrency);
            var results = new ConcurrentBag<TResult>();

            var tasks = new List<Task>();
            foreach (var input in inputs)
            {
                await semaphore.WaitAsync();
                tasks.Add(Task.Run(async () =>
                {
                    try
                    {
                        var result = await taskFunc(input);
                        results.Add(result);
                    }
                    catch (Exception ex)
                    {
                        Console.WriteLine($"Exception {ex.Message}");
                        results.Add(default);
                    }
                    finally
                    {
                        semaphore.Release();
                    }
                }));
            }
            // 等待所有任务完成
            await Task.WhenAll(tasks);
            return results;
        }
    }

    /// <summary>
    /// 测试示例
    /// </summary>
    public class Test
    {
        private static readonly HttpClient _httpClient = new HttpClient();
        public async void RunTest()
        {
            _httpClient.Timeout = TimeSpan.FromSeconds(29);
            var _list = Enumerable.Range(1, 100).ToList();
            var list = _list.Select(s => new { id = s, value = 0 }).ToList();
            list.Add(new { id = 101, value = 30 });

            async Task<string> ExampleTask(dynamic input)
            {
                var response = await _httpClient.GetAsync($"http://localhost:5220/api/Func/Sleep?seconds={input}");
                var _res = "------";
                if (response.IsSuccessStatusCode)
                {
                    _res = await response.Content.ReadAsStringAsync();
                }
                Console.WriteLine($"{DateTime.Now}___{input}___{_res}");

                return _res;
            }

            // 调用通用方法，执行任务
            var results = await MultiTaskExecutor.ExecuteTasksAsync(ExampleTask, list, 1);
        }
    }
}
